package cn.sciento.export;

import javax.servlet.http.HttpServletResponse;

import cn.sciento.core.exception.CommonException;
import cn.sciento.core.exception.ExceptionResponse;
import org.apache.commons.collections4.CollectionUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import cn.sciento.export.annotation.ExcelExport;
import cn.sciento.export.constant.ExportType;
import cn.sciento.export.util.ResponseWriter;
import cn.sciento.export.vo.ExportColumn;
import cn.sciento.export.vo.ExportParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

@Aspect
public class ExcelExportAop {
    private static final Logger LOGGER = LoggerFactory.getLogger(ExcelExportAop.class);

    private ExportDataHelper exportDataHelper;

    private ExportColumnHelper exportColumnHelper;

    public ExcelExportAop(ExportDataHelper exportDataHelper, ExportColumnHelper exportColumnHelper) {
        this.exportDataHelper = exportDataHelper;
        this.exportColumnHelper = exportColumnHelper;
    }

    @Around("@annotation(excelExport)")
    public Object excelExport(ProceedingJoinPoint joinPoint, ExcelExport excelExport) throws Throwable {
        HttpServletResponse response = null;
        ExportParam exportParam = null;
        Object[] args = joinPoint.getArgs();
        for (Object arg : args) {
            if (arg instanceof HttpServletResponse) {
                response = (HttpServletResponse) arg;
            } else if (arg instanceof ExportParam) {
                exportParam = (ExportParam) arg;
            }
        }
        Assert.notNull(response, "HttpServletResponse must not be null.");
        Assert.notNull(exportParam, "ExportParam must not be null.");
        Assert.notNull(exportParam.getExportType(), "ExportType must not be null.");
        if (!ExportType.match(exportParam.getExportType()))
            return joinPoint.proceed();
        if (ExportType.COLUMN.equals(exportParam.getExportType())) {
            ExportColumn exportColumn = this.exportColumnHelper.getExportColumn(excelExport);
            ResponseWriter.write(response, exportColumn);
            return null;
        }
        if (CollectionUtils.isEmpty(exportParam.getIds())) {
            ExceptionResponse exceptionResponse = new ExceptionResponse("export.column.least-one");
            LOGGER.warn(exceptionResponse.getMessage());
            ResponseWriter.write(response, exceptionResponse);
            return null;
        }
        try {
            doExportByType(exportParam.getExportType(), joinPoint, excelExport, response);
        } catch (CommonException e) {
            LOGGER.warn("excel export error.", (Throwable) e);
            ExceptionResponse exceptionResponse = new ExceptionResponse(e.getCode());
            ResponseWriter.write(response, exceptionResponse);
        } catch (Throwable e) {
            LOGGER.warn("excel export error.", e);
            ExceptionResponse exceptionResponse = new ExceptionResponse("export.error");
            exceptionResponse.setException(e.getMessage());
            ResponseWriter.write(response, exceptionResponse);
        }
        return null;
    }

    private void doExportByType(ExportType type, ProceedingJoinPoint joinPoint, ExcelExport excelExport, HttpServletResponse response) throws Exception {
        if (ExportType.DATA.equals(type)) {
            this.exportDataHelper.exportExcel(joinPoint, excelExport, response);
        } else if (ExportType.TEMPLATE.equals(type)) {
            this.exportDataHelper.exportTemplate(joinPoint, excelExport, response);
        }
    }
}
